﻿using LxCore;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace LxCore
{
    public class JointCond : JsObject, IIdentity
    {
        public JointCond(FvJoint joint)
        {
            Joint = joint;
        }
        public FvJoint Joint;
        public ZoneCond OZoneCond => ResHelper.GetCond(Joint.OZone);
        public BoundCond OBoundCond => ResHelper.GetCond(Joint.OBound);
        public ZoneCond NZoneCond => ResHelper.GetCond(Joint.NZone);
        public BoundCond NBoundCond => ResHelper.GetCond(Joint.NBound);
        public string Name
        {
            get => Joint.Name;
            set
            {
                Joint.Name = value;
                RaisePropertyChanged(nameof(Name));
            }
        }
        public int ID
        {
            get => Joint.ID;
            set
            {
                Joint.ID = value;
                RaisePropertyChanged(nameof(ID));
            }
        }

        public bool IsEnabled
        {
            get => _IsEnable && OZoneCond.PhysicalModel != null && NZoneCond.PhysicalModel != null;
            set
            {
                _IsEnable = value;
                RaisePropertyChanged(nameof(IsEnabled));
                CheckSetJoint();
            }
        }
        private bool _IsEnable = true;

        public BoundTypes[] AvaliableJointTypes
        {
            get => _AvaliableJointTypes;
            set { _AvaliableJointTypes = value; RaisePropertyChanged(nameof(AvaliableJointTypes)); }
        }
        private BoundTypes[] _AvaliableJointTypes;
        public BoundTypes JointType
        {
            get => _JointType;
            set
            {
                _JointType = value;
                RaisePropertyChanged(nameof(JointType));
            }
        }
        private BoundTypes _JointType = BoundTypes.接触壁面;
        public void CheckSetJoint()
        {
            var OZoneSet = ResHelper.GetCond(Joint.OZone);
            var NZoneSet = ResHelper.GetCond(Joint.NZone);
            if (OZoneSet.PhysicalModel == null || NZoneSet.PhysicalModel == null)
            {
                AvaliableJointTypes = null;
            }
            else
            {
                switch (OZoneSet.PhysicalModel.PhysicalType, NZoneSet.PhysicalModel.PhysicalType)
                {
                    case (PhysicalTypes.固体, PhysicalTypes.固体):
                        AvaliableJointTypes = LxSim.Sim.Conditions.SolidSolidJointTypes;
                        break;
                    case (PhysicalTypes.流体, PhysicalTypes.流体):
                        AvaliableJointTypes = LxSim.Sim.Conditions.FluidFluidJointTypes;
                        break;
                    case (PhysicalTypes.固体, PhysicalTypes.流体):
                    case (PhysicalTypes.流体, PhysicalTypes.固体):
                        AvaliableJointTypes = LxSim.Sim.Conditions.SolidFluidJointTypes;
                        break;
                    default: throw new Exception("无可用接触边界条件");
                }
                if (!AvaliableJointTypes.Contains(JointType))
                {
                    JointType = AvaliableJointTypes[0];
                }
            }

        }
        public FieldBase<double> EnergySource_b
        {
            get => _EnergySource_b;
            set { _EnergySource_b = value; RaisePropertyChanged(nameof(EnergySource_b)); }
        }
        private FieldBase<double> _EnergySource_b = new ConstField.Double(0);
        public FieldBase<double> EnergySource_a
        {
            get => _EnergySource_a;
            set { _EnergySource_a = value; RaisePropertyChanged(nameof(EnergySource_a)); }
        }
        private FieldBase<double> _EnergySource_a = new ConstField.Double(0);
        public FieldBase<double> ThermalResistance
        {
            get => _ThermalResistance;
            set { _ThermalResistance = value; RaisePropertyChanged(nameof(ThermalResistance)); }
        }
        private FieldBase<double> _ThermalResistance = new ConstField.Double(0);

        public override void FromJsonKV(string key, IJsonReader jsReader)
        {
            switch (key)
            {
                case nameof(IsEnabled): IsEnabled = jsReader.ReadBool(); break;
                case nameof(JointType): JointType = jsReader.ReadEnum<BoundTypes>(); break;
                case nameof(EnergySource_a): jsReader.ReadObject(EnergySource_a, e => EnergySource_a = e); break;
                case nameof(EnergySource_b): jsReader.ReadObject(EnergySource_b, e => EnergySource_b = e); break;
                case nameof(ThermalResistance): jsReader.ReadObject(ThermalResistance, e => ThermalResistance = e); break;
                default: base.FromJsonKV(key, jsReader); break;
            }
        }
        public override void ToJsonKV(IJsonWriter jsWriter)
        {
            base.ToJsonKV(jsWriter);
            jsWriter.WriteBool(nameof(IsEnabled), IsEnabled);
            jsWriter.WriteEnum(nameof(JointType), JointType);
            bool isEnergyEnabled(PhysicalModel physicalModel) => physicalModel != null && physicalModel.IsEnergyEnabled;
            if (isEnergyEnabled(OZoneCond.PhysicalModel) && isEnergyEnabled(NZoneCond.PhysicalModel))
            {
                jsWriter.WriteObject(nameof(EnergySource_a), EnergySource_a, true);
                jsWriter.WriteObject(nameof(EnergySource_b), EnergySource_b, true);
                jsWriter.WriteObject(nameof(ThermalResistance), ThermalResistance, true);
            }
        }
    }
}